
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <glib-2.0/glib.h>
int serial_open(const char *node, int baud, uint8_t data_bit, char parity,
    uint8_t stop_bit)
{
	int rc = 0, fd = 0;
  struct termios tios;

  fd = open(node, O_RDWR|O_NOCTTY| O_NONBLOCK);
	if (fd < 0) {
		printf("[error]filename:%s open error\n", node);
		rc = fd;
		goto out;
	}
  tcgetattr(fd, &tios);
  speed_t baudrate;
  switch (baud) {
		case 50:
			baudrate = B50;
			break;
		case 150:
			baudrate = B150;
			break;
		case 110:
			baudrate = B110;
			break;
		case 300:
			baudrate = B300;
			break;
		case 600:
			baudrate = B600;
			break;
		case 1200:
			baudrate = B1200;
			break;
		case 2400:
			baudrate = B2400;
			break;
		case 4800:
			baudrate = B4800;
			break;
		case 9600:
			baudrate = B9600;
			break;
		case 19200:
			baudrate = B19200;
			break;
		case 38400:
			baudrate = B38400;
			break;
		case 57600:
			baudrate = B57600;
			break;
		case 115200:
			baudrate = B115200;
			break;
		case 460800:
			baudrate = B460800;
			break;
		default:
			baudrate = B9600;
  }
  if ((cfsetispeed(&tios, baudrate) < 0) || (cfsetospeed(&tios, baudrate) < 0)) {
    close(fd);
		goto out;
  }
  tios.c_cflag |= (CREAD | CLOCAL);
  tios.c_cflag &= ~CSIZE;
  switch (data_bit) {
		case 5:
			tios.c_cflag |= CS5;
			break;
		case 6:
			tios.c_cflag |= CS6;
			break;
		case 7:
			tios.c_cflag |= CS7;
			break;
		case 8:
		default:
			tios.c_cflag |= CS8;
			break;
  }
  if (stop_bit == 1)
		tios.c_cflag &=~ CSTOPB;
  else
		tios.c_cflag |= CSTOPB;
  if (parity == 'N') {
    tios.c_cflag &=~ PARENB;
  } else if (parity == 'E') {
    tios.c_cflag |= PARENB;
    tios.c_cflag &=~ PARODD;
  } else {
    tios.c_cflag |= PARENB;
    tios.c_cflag |= PARODD;
  }
  tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  if (parity == 'N') {
    tios.c_iflag &= ~INPCK;
  } else {
    tios.c_iflag |= INPCK;
  }
  tios.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL);
  tios.c_iflag |= IGNBRK;
  tios.c_iflag |= IGNPAR;
  tios.c_oflag &=~ OPOST;
  tios.c_cc[VMIN] = 0;
  tios.c_cc[VTIME] = 0;
  if (tcsetattr(fd, TCSANOW, &tios) < 0) {
    close(fd);
    printf("[error] init\n");
    goto out;
  }
  printf("%d[%s]baud:%d,data_bit:%d,parity:%d,stop_bit:%d\n",
			fd, node, baud, data_bit, parity, stop_bit);
	rc = fd;
out:
	return rc;
}
gboolean serial_read(GIOChannel *channel, GIOCondition condition, gpointer data)
{
    gchar buffer[1024];
    gsize len;
    GError *error = NULL;
    g_io_channel_read_chars(channel, buffer, sizeof(buffer), &len, &error);
    if (error != NULL) {
        g_print("Error reading from the serial port: %s\n", error->message);
        g_error_free(error);
        return FALSE;
    }
    
    int i;
    //  len = read(g_io_channel_unix_get_fd (channel), buffer, sizeof(buffer) - 1);
    if (len) {
      g_print ("++++:");
      for (i = 0; i < len; i++) {
        g_print ("%02x ", buffer[i]);
      }
      g_print ("\n");
    }
    return TRUE;
}
gpointer serial_write (gpointer userdata)
{
  GIOChannel *channel = NULL;
  gchar *buffer = "aas";
  gsize len;
  gint rc, fd;
  GError *error = NULL;

  channel = userdata;
  while (1) {
    fd = g_io_channel_unix_get_fd (channel);
   // len = write (fd, "ss", 2);
    rc = g_io_channel_write_chars(channel, buffer, 2, &len, &error);
    if (rc != G_IO_STATUS_NORMAL) {
      g_print("Error writing to serial: %s\n", error->message);
      g_error_free(error);
    } else {
      rc = g_io_channel_flush(channel, &error);
      if (rc != G_IO_STATUS_NORMAL) {
        g_print("Error flushing serial: %s\n", error->message);
        g_error_free(error);
      }
      if (len)
        g_print ("[%d]----:%"G_GSIZE_FORMAT"\n", fd, len);
    }
    sleep (1);
  }
}

int main(int argc, char **argv) {
  g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
  //const gchar *portname = "/dev/ttyUSB0";
  const gchar *portname = argv[1];
  int fd;
  GError *error = NULL;
  GIOChannel *channel = NULL;
  GIOCondition condition = 0;
  
  fd = serial_open (portname, 9600, 8, 'N', 1);
  g_print("portname:%s fd:%d\n", portname, fd);
  channel = g_io_channel_unix_new(fd);
  if (channel == NULL) {
      g_print("Failed to open the serial port\n");
      return 1;
  }
  g_io_channel_set_encoding (channel, NULL, &error);
  condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
  g_io_add_watch(channel, condition, serial_read, NULL);
  
  // 进行其他操作..
#if 1
  GThread *thread;
  thread = g_thread_new ("write", serial_write, channel);
//  g_thread_unref (thread);
#endif
  
  g_main_loop_run(g_main_loop_new(NULL, FALSE));

  close(g_io_channel_unix_get_fd(channel));
  g_io_channel_unref(channel);
  
  return 0;
}


